﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Xml;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;



namespace GraphPainterASP.NET.Controllers
{

    public class GraphController : Controller
    {
        private Graph GraphValues1;
        private int VidstupHorizontal = 50;
        private int VidstupVertical = 20;
        private Bitmap Bitmap_Temp;
        private Graphics G;
        private Font Font_Common = new Font("Arial", 8);
        private Pen Pen_Special = new Pen(Color.FromArgb(255, 150, 0), 2);
        private Pen Pen_Main = new Pen(Color.FromArgb(232, 0, 0), 2);
        private Pen Pen_BorderLines = new Pen(Color.FromArgb(194, 194, 194), 1);
        private SolidBrush SolidBrush_Font = new SolidBrush(Color.FromArgb(24, 24, 24));
        private SolidBrush SolidBrush_Special = new SolidBrush(Color.FromArgb(255, 150, 0));
        private SolidBrush SolidBrush_Background = new SolidBrush(Color.FromArgb(247, 247, 247));
        private SolidBrush SolidBrush_Bottom = new SolidBrush(Color.FromArgb(255, 230, 230));

        public ActionResult Graph()
        {
            return View();
        }
        private List<GraphValues> ParseXML(string FileUrl)
        {
            List<GraphValues> Values_Temp = new List<GraphValues>();
            string Now = "";
            string AverageValue_Temp = "";
            string MaxValue_Temp = "";
            string MinValue_Temp = "";

            XmlTextReader Reader = new XmlTextReader(FileUrl);
            while (Reader.Read())
                switch (Reader.NodeType)
                {
                    case XmlNodeType.Element:
                        if (Reader.Name == "AverageValue")
                            Now = "AverageValue";
                        if (Reader.Name == "MaxValue")
                            Now = "MaxValue";
                        if (Reader.Name == "MinValue")
                            Now = "MinValue";
                        break;

                    case XmlNodeType.Text:
                        if (Now == "AverageValue")
                            AverageValue_Temp = Reader.Value.Replace('.', ',');
                        if (Now == "MaxValue")
                            MaxValue_Temp = Reader.Value.Replace('.', ',');
                        if (Now == "MinValue")
                            MinValue_Temp = Reader.Value.Replace('.', ',');
                        break;

                    case XmlNodeType.EndElement:
                        if (Reader.Name == "Rate")
                            Values_Temp.Add(new GraphValues(Convert.ToDouble(MaxValue_Temp), Convert.ToDouble(MinValue_Temp), Convert.ToDouble(AverageValue_Temp)));
                        break;
                }

            return Values_Temp;
        }
        public void PaintAll(string Period, string Date, string Currency)
        {
            try
            {
                string FileUrl = "http://localhost:34644/GetService.svc/Chart" + Period + "/" + Date + "/" + Currency;
                GraphValues1 = new Graph(ParseXML(FileUrl));
            }
            catch (Exception ex)
            {

            }

            //create image
            Bitmap_Temp = new Bitmap(400, 180);
            G = Graphics.FromImage(Bitmap_Temp);
            G.FillRectangle(SolidBrush_Background, 0, 0, Bitmap_Temp.Width, Bitmap_Temp.Height);

            try
            {
                if (GraphValues1.Values.Count > 0)
                {
                    GraphValues1.SetValues();

                    if (GraphValues1.Max > GraphValues1.Min)
                    {
                        double KoefH = (double)(Bitmap_Temp.Height - 2 * VidstupVertical) / (GraphValues1.Max - GraphValues1.Min);
                        double KoefW = (double)(Bitmap_Temp.Width - 2 * VidstupHorizontal) / (GraphValues1.Values.Count - 1);

                        BrushBottom(KoefH, KoefW);
                        PaintNet(KoefH, KoefW);
                        PaintMax(KoefH, KoefW);
                        PaintMin(KoefH, KoefW);
                        PaintAverage(KoefH, KoefW);
                    }
                    else
                        PaintAverage();
                }
                else
                    G.DrawString("Not enough data at this file", Font_Common, SolidBrush_Font, new Point((Bitmap_Temp.Width / 3), (Bitmap_Temp.Height / 2)));
            }
            catch (Exception ex)
            {
                G.DrawString(ex.Data.ToString(), Font_Common, SolidBrush_Font, new Point((Bitmap_Temp.Width / 4), (Bitmap_Temp.Height / 2)));
            }
            finally
            {
                //save image
                try
                {
                    Bitmap_Temp.Save(@"D:\TFS\GraphPainterASP.NET\GraphImg\Pic_Temp.png", ImageFormat.Png);
                    Bitmap_Temp.Dispose();
                }
                catch (Exception ex)
                {

                }
            }
        }
        private void PaintNet(double KoefH, double KoefW)
        {
            for (int i = 0; i < GraphValues1.Values.Count; i++)
            {
                G.DrawLine(Pen_BorderLines, VidstupHorizontal + (int)(i * KoefW), 
                                           VidstupVertical, 
                                           VidstupHorizontal + (int)(i * KoefW), 
                                           Bitmap_Temp.Height - VidstupVertical);
                G.DrawLine(Pen_BorderLines, VidstupHorizontal,
                                           VidstupVertical + ((Bitmap_Temp.Height - 2 * VidstupVertical) * i / (GraphValues1.Values.Count - 1)), 
                                           Bitmap_Temp.Width - VidstupHorizontal,
                                           VidstupVertical + ((Bitmap_Temp.Height - 2 * VidstupVertical) * i / (GraphValues1.Values.Count - 1)));
            }
        }
        private void PaintMax(double KoefH, double KoefW)
        {
            //graph
            double Max = GraphValues1.Max;
            for (int i = 0; i < GraphValues1.Values.Count - 1; i++)
                G.DrawLine(Pen_Special, (int)(VidstupHorizontal + i * KoefW),
                                    (int)(VidstupVertical + (Max - GraphValues1.Values[i].Max) * KoefH),
                                    (int)(VidstupHorizontal + (i + 1) * KoefW),
                                    (int)(VidstupVertical + (Max - GraphValues1.Values[i + 1].Max) * KoefH));

            //text
            G.DrawString(string.Format("{0:0.0000}", Max), Font_Common, SolidBrush_Font, new Point(6, VidstupVertical - 6));
        }
        private void PaintMin(double KoefH, double KoefW)
        {
            //graph
            double Max = GraphValues1.Max;
            for (int i = 0; i < GraphValues1.Values.Count - 1; i++)
                G.DrawLine(Pen_Special, (int)(VidstupHorizontal + i * KoefW),
                                    (int)(VidstupVertical + (Max - GraphValues1.Values[i].Min) * KoefH),
                                    (int)(VidstupHorizontal + (i + 1) * KoefW),
                                    (int)(VidstupVertical + (Max - GraphValues1.Values[i + 1].Min) * KoefH));

            //text
            double Min = GraphValues1.Min;
            G.DrawString(string.Format("{0:0.0000}", Min), Font_Common, SolidBrush_Font, new Point(6, (Bitmap_Temp.Height - VidstupVertical - 6)));
        }
        private void PaintAverage()
        {
            double Max = GraphValues1.Max;
            G.DrawString(string.Format("{0:0.0000}", Max), Font_Common, SolidBrush_Font, new Point(0, (Bitmap_Temp.Height / 2)));
            G.DrawLine(Pen_Main, VidstupHorizontal, Bitmap_Temp.Height / 2, (Bitmap_Temp.Width - VidstupHorizontal), Bitmap_Temp.Height / 2);
        }
        private void PaintAverage(double KoefH, double KoefW)
        {
            double Max = GraphValues1.Max;
            for (int i = 0; i < GraphValues1.Values.Count - 1; i++)
                G.DrawLine(Pen_Main, (int)(VidstupHorizontal + i * KoefW),
                                    (int)(VidstupVertical + (Max - GraphValues1.Values[i].Average) * KoefH), 
                                    (int)(VidstupHorizontal + (i + 1) * KoefW),
                                    (int)(VidstupVertical + (Max - GraphValues1.Values[i + 1].Average) * KoefH));
        }
        private void BrushBottom(double KoefH, double KoefW)
        {
            double Max = GraphValues1.Max;
            for (int i = 0; i < GraphValues1.Values.Count - 1; i++)
            {
                Point[] CurvePoints = { new Point((int)(VidstupHorizontal + i * KoefW), Bitmap_Temp.Height - VidstupVertical),
                                        new Point((int)(VidstupHorizontal + i * KoefW), (int)(VidstupVertical + (Max - GraphValues1.Values[i].Average) * KoefH)),
                                        new Point((int)(VidstupHorizontal + (i + 1) * KoefW), (int)(VidstupVertical + (Max - GraphValues1.Values[i + 1].Average) * KoefH)), 
                                        new Point((int)(VidstupHorizontal + (i + 1) * KoefW), Bitmap_Temp.Height - VidstupVertical) };
                G.FillPolygon(SolidBrush_Bottom, CurvePoints);
            }
        }

    }

}
